#include <iostream>
#include <string>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define CHECK_RET(q) if((q)==false){return -1;}
#define MAX_LISTEN 5

struct cal_t{
    int num1;
    int num2;
    char op;
};

class TcpSocket{
    private:
        int _sockfd;
    public:
        TcpSocket():_sockfd(-1){}
        int GetFd() {
            return _sockfd;
        }
        void SetFd(int fd){
            _sockfd = fd;
        }
        bool Socket(){
            //int socket(int domain,  int type,  int protocol)
            _sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
            if (_sockfd < 0) {
                perror("socket error");
                return false;
            }
            return true;
        }//创建套接字
        bool Bind(const std::string &ip,  int port){
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_port = htons(port);
            addr.sin_addr.s_addr = inet_addr(ip.c_str());
            socklen_t len = sizeof(addr);
            if (bind(_sockfd, (struct sockaddr*)&addr, len) < 0) {
                perror("bind error");
                return false;
            }
            return true;
        }//绑定地址信息
        bool Listen(int backlog = MAX_LISTEN){
            //int listen(int sockfd,  int backlog)
            if (listen(_sockfd, backlog) < 0)  {
                perror("listen error");
                return false;
            }
            return true;
        }//服务端开始监听
        bool Connect(const std::string &srv_ip, int srv_port){
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_port = htons(srv_port);
            addr.sin_addr.s_addr = inet_addr(srv_ip.c_str());
            socklen_t len = sizeof(addr);
            //int connect(int sockfd,  struct sockaddr *srv_addr,  socklen_t len)
            if (connect(_sockfd, (struct sockaddr*)&addr, len) < 0) {
                perror("connect error");
                return false;
            }
            return true;
        }//向服务端发起连接请求 
        bool Accept(TcpSocket *new_sock, std::string *cli_ip, int *cli_port){
            //int accept(int sockfd,  struct sockaddr *addr,  socklen_t *len);
            struct sockaddr_in addr;
            socklen_t len = sizeof(addr);
            //这里是获取新建连接，地址信息是接口内部在获取了一个新建连接的同时赋予
            //这个连接对应的客户端的地址信息
            int new_fd = accept(_sockfd, (struct sockaddr*)&addr, &len);
            if (new_fd < 0) {
                perror("accept error");
                return false;
            }
            new_sock->_sockfd = new_fd;
            if (cli_ip != NULL) *cli_ip = inet_ntoa(addr.sin_addr);
            if (cli_port != NULL) *cli_port = ntohs(addr.sin_port);
            return true;
        }//获取新建连接
        bool Send(const std::string &data) {
            //ssize_t send(int sockfd, void *data, int len, int flag);
            ssize_t ret = send(_sockfd, data.c_str(), data.size(), 0);
            if (ret < 0) {
                perror("send error");
                return false;
            }
            return true;
        }
        bool Recv(std::string *buf) {
            //ssize_t recv(int sockfd, void *buf, int len,  int flag);
            char tmp[4096] = {0};
            ssize_t ret = recv(_sockfd, tmp, 4096, 0);
            if (ret < 0) {
                perror("recv error");
                return false;
            }else if (ret == 0) {
                std::cout << "peer shutdown!\n";
                return false;
            }
            buf->assign(tmp, ret);
            return true;
        }
        bool Close() {
            if (_sockfd > 0){
                close(_sockfd);
                _sockfd = -1;
            }
            return true;
        }
};
